using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightUtilities;
using System.Collections;

namespace PHSRAG.Insight21.Admin.Controls
{
	/// <summary>
	///	Allows users to add or remove principal investigators (PIs) that
	///	make up a lab.
	/// </summary>
	public partial class EditAdminLabInvestigators : System.Web.UI.UserControl
	{
		#region Constants
		private const string ClosePopupClientScriptKey = "ScriptKey_FF9667EF-3941-4a54-98BA-11FF8A9F633B";
		#endregion

		#region Instance Variables (Private)
		/// <summary>Policy used for caching objects to be used across pages. </summary>
		private	Policy.ICachePolicy		pageCachePolicy;
		/// <summary>Policy used for caching business objects.</summary>
		private	Policy.ICachePolicy		objectCachePolicy;
		#endregion

		#region Private Properties
		/// <summary>
		/// Gets the Lab being updated. Checks the cache first, if empty
		/// retrieves it from the database.
		/// </summary>
		private Lab CurrentLab
		{
			get 
			{
				Lab lab = objectCachePolicy.GetCachedObject(Lab.CacheKey) as Lab;
				if (lab == null)
				{
					lab = new Lab(objectCachePolicy);
					Hashtable incomingData = (Hashtable)pageCachePolicy.GetCachedObject(Keys.IncomingDataKey);
					lab.Load(Utility.DataAccess.GetConnectionString(), Convert.ToInt32(incomingData[Keys.LabIdKey]));
					lab.Cache();
				}			
				return lab;
			}		
		}
		#endregion

		#region Event Handlers
		/// <summary>
		/// Sets the pop up page title, lab basic information controls (name, description and organization)
		/// and adds window close code for cancel button.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void Page_Load(object sender, System.EventArgs e)
		{
			if (!IsPostBack) 
			{
				((HtmlGenericControl)Page.FindControl("pageTitle")).InnerText = "Edit Lab Investigators";
				cancel.Attributes["onclick"] = "window.close()";
				Lab lab = CurrentLab;
				LoadLabBasicInfoControls(lab);
				LoadAssignedPIList(lab);
				LoadAvailablePIList(lab);
			}
		}
		/// <summary>
		/// Persists lab changed to the database and closes the popup.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnSave(object sender, EventArgs e)
		{
			try 
			{
				CurrentLab.Save(Utility.DataAccess.GetConnectionString(), LabCommandType.EditPIs);

				// close the popup and refresh the opening page so that it displays the new PI list
				Page.ClientScript.RegisterClientScriptBlock(GetType( ), ClosePopupClientScriptKey, "<script language='javascript'>window.opener.location.reload();window.close();</script>");
			} 
			catch (Exception ex) 
			{
				annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
				Utility.ExceptionReport.WriteToEventLog("EditAdminLabInvestigators", ex, true, Utility.ExceptionReport.ReportType.Error);
			}
		}
		/// <summary>
		/// Removes selected item(s) from available list and adds them to assigned list.
		/// Also keeps in-memory assigned and available lists in sync with the changes.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnAdd(object sender, EventArgs e)
		{
			ListItem item = null;
			Lab lab = CurrentLab;
			DataTable assignedListDataTable = lab.AssignedPIs;
			DataTable availableListDataTable = lab.AvailablePIs;
			while ((item = availableList.SelectedItem) != null)
			{
				item.Selected = false;
				assignedList.Items.Add(item);
				availableList.Items.Remove(item);

				DataRow newRow = assignedListDataTable.NewRow();
				assignedListDataTable.Rows.Add(newRow);
				newRow["PersonId"] = Convert.ToInt32(item.Value);
				newRow["LabId"] = lab.Id;
				newRow["PIName"] = item.Text;
				availableListDataTable.Rows.Remove(availableListDataTable.Select(string.Format("Id = {0}", item.Value))[0]);
			}
			lab.Cache();
		}
		
		/// <summary>
		/// Removes selected items from assigned list and adds them to available list.
		/// Also keeps in-memory assigned and available lists in sync with the changes.
		/// </summary>
		/// <param name="sender">The object raising the event.</param>
		/// <param name="e">Information about the event itself.</param>
		protected void OnRemove(object sender, EventArgs e)
		{
			ListItem item = null;
			Lab lab = CurrentLab;
			DataTable assignedListDataTable = lab.AssignedPIs;
			DataTable availableListDataTable = lab.AvailablePIs;
			while ((item = assignedList.SelectedItem) != null) 
			{
				item.Selected = false;
				availableList.Items.Add(item);
				assignedList.Items.Remove(item);

				DataRow newRow = availableListDataTable.NewRow();
				availableListDataTable.Rows.Add(newRow);
				newRow["PIName"] = item.Text;
				newRow["Id"] = Convert.ToInt32(item.Value);
				assignedListDataTable.Select(string.Format("PersonId = {0}", item.Value))[0].Delete();
			}
			lab.Cache();
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Supplies lab name, description and organization labels with values.
		/// </summary>
		/// <param name="lab">The lab whose basic info is displayed.</param>
		private void LoadLabBasicInfoControls(Lab lab) 
		{
			labName.Text = lab.Name;
			labDescription.Text = lab.Description;
			labOrganization.Text = lab.Organization;
		}
		/// <summary>
		/// Loads available PI list box. Those PIs already
		/// in the lab (in assigned list) are ignored. Consequently, Assigned list
		/// has to be loaded before available list. 
		/// </summary>
		/// <param name="lab">The lab whose PIsare displayed.</param>
		private void LoadAvailablePIList(Lab lab)
		{
			if (!lab.IsAvailablePIDataTableLoaded)
			{
				UserContext userContext = objectCachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
				System.Diagnostics.Debug.Assert(userContext != null);
				lab.LoadAvailablePIs(userContext.DomainUserId);
				lab.Cache();
			}
			DataTable availablePIsDataTable = lab.AvailablePIs;
			foreach (DataRow piRow in availablePIsDataTable.Rows)
			{
				string assignedListValue = Convert.ToString(piRow["Id"]);
				if (assignedList.Items.FindByValue(assignedListValue) == null)
					availableList.Items.Add(new ListItem(piRow["PIName"].ToString(), assignedListValue));
			}		
		}
		/// <summary>
		/// Loads assigned PI list box.
		/// </summary>
		/// <param name="lab">The lab whose PIsare displayed.</param>
		private void LoadAssignedPIList(Lab lab)
		{
			DataTable assignedPIsDataTable = lab.AssignedPIs;
			foreach (DataRow piRow in assignedPIsDataTable.Rows) 
				assignedList.Items.Add(new ListItem(piRow["PIName"].ToString(), Convert.ToString(piRow["PersonId"])));
		}
		#endregion

		#region Web Form Designer generated code
		/// <summary>
		/// Wires up events.
		/// </summary>
		/// <param name="e">Information accompanying the event itself.</param>
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);

			objectCachePolicy = (Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey];
			pageCachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];

			ID = "editAdminLabInvestigators";
		}
		
		/// <summary>
		///		Required method for Designer support - do not modify
		///		the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
		}
		#endregion
	}
}
